/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#include "StdAfx.h"
#include ".\marpcachelist.h"

//---------------------------------------------------------------------------

MArpCacheList::MArpCacheList(void) : MFileConfig()
{
}

MArpCacheList::~MArpCacheList(void)
{
	CleanUp();
}

//---------------------------------------------------------------------------

void MArpCacheList::CleanUp(void)
{
	MArpCacheRec *elem;

	for(itor=theVector.begin(); itor!=theVector.end(); itor++){
		elem = *itor;
		if(elem!=NULL){
			*itor = NULL;
			delete elem;
		}
	}
	theVector.clear();
}

//---------------------------------------------------------------------------

MArpCacheRec* MArpCacheList::CreateElement(void)
{
	MArpCacheRec *elem;

	try{
		elem = new MArpCacheRec;
	}
	catch(...){
		elem = NULL;
	}

	return elem;
}

//---------------------------------------------------------------------------

MArpCacheRec* MArpCacheList::FindElementByIP(DWORD ipIn)
{
	MArpCacheRec* elem;
	MArpCacheRec* res;

	res = NULL;
	for(itor=theVector.begin(); itor!=theVector.end() && res==NULL; itor++){
		elem = *itor;
		if(elem!=NULL){
			if(!elem->v6)
				if(elem->addrIP.GetD()==ipIn)
					res = elem;
		}
	}

	return res;
}

MArpCacheRec* MArpCacheList::FindElementByIPv6(in_addr6* ipIn)
{
	MArpCacheRec* elem;
	MArpCacheRec* res;

	res = NULL;
	if(ipIn==NULL) return res;

	for(itor=theVector.begin(); itor!=theVector.end() && res==NULL; itor++){
		elem = *itor;
		if(elem!=NULL){
			if(elem->v6)
				if(elem->addrIPv6.IsEqualWith(ipIn))
					res = elem;
		}
	}

	return res;
}

//---------------------------------------------------------------------------

bool MArpCacheList::Add(MArpCacheRec* recIn)
{
	MArpCacheRec *elem;
	in_addr6 ia6;
	int cnt;

	if(recIn==NULL) return true;

	if(recIn->v6){
		recIn->addrIPv6.Get(&ia6);
		elem = FindElementByIPv6(&ia6);
	}
	else{
		elem = FindElementByIP(recIn->addrIP.GetD());
	}

	if(elem!=NULL){
		elem->addrMAC.LoadFromPointer(&recIn->addrMAC);
		return true;
	}

	elem = CreateElement();
	if(elem==NULL) return false;

	elem->LoadFromPointer(recIn);

	cnt = (int)theVector.size();
	theVector.push_back(elem);
	cnt = (int)theVector.size() - cnt;
	if(cnt!=1){
		delete elem;
		return false;
	}

	return true;
}

//---------------------------------------------------------------------------

int MArpCacheList::GetSize(void)
{
	return (int)theVector.size();
}

MArpCacheRec* MArpCacheList::GetByIdx(int idxIn)
{
	if(idxIn<0)          return NULL;
	if(idxIn>=GetSize()) return NULL;

	return theVector[idxIn];
}

//---------------------------------------------------------------------------

void MArpCacheList::InternalInit(void)
{
	CleanUp();
}

//---------------------------------------------------------------------------

bool MArpCacheList::InternalProcessLine(char* buf)
{
	MArpCacheRec rec;
	CString str;

	if(buf==NULL){
		// nothing to process
		return true;
	}

	str = buf;
	if(!rec.FromString(str))
		return false;

	if(!Add(&rec))
		return false;

	return true;
}

//---------------------------------------------------------------------------

bool MArpCacheList::InternalSave(void)
{
	MArpCacheRec *elem;
	CString str;

	if(!WriteEmptyCommentLine()) return false;
	if(!WriteCommentLine(_T("CHScanner - ARP Cache Table"))) return false;
	if(!WriteEmptyCommentLine()) return false;
	if(!AddTimeStampAsComment()) return false;
	if(!WriteEmptyCommentLine()) return false;

	if(!WriteEmptyLine()) return false;

	for(itor=theVector.begin(); itor!=theVector.end(); itor++){
		elem = *itor;
		if(elem!=NULL){
			str = elem->ToString();
			if(!WriteLine(str))
				return false;
		}
	}

	if(!WriteEmptyLine()) return false;

	return true;
}

//---------------------------------------------------------------------------

bool MArpCacheList::GetRecordByIPv4(DWORD ipIn, MArpCacheRec* recIn)
{
	MArpCacheRec *elem;
	bool found;

	if(recIn==NULL) return false;

	found = false;
	for(itor=theVector.begin(); itor!=theVector.end() && !found; itor++){
		elem = *itor;
		if(elem!=NULL){
			if(!elem->v6){
				if(elem->addrIP.GetD()==ipIn){
					recIn->LoadFromPointer(elem);
					found = true;
				}
			}
		}
	}

	return found;
}

bool MArpCacheList::GetRecordByIPv6(in_addr6* ipIn, MArpCacheRec* recIn)
{
	MArpCacheRec *elem;
	bool found;

	if(recIn==NULL) return false;
	if(ipIn==NULL) return false;

	found = false;
	for(itor=theVector.begin(); itor!=theVector.end() && !found; itor++){
		elem = *itor;
		if(elem!=NULL){
			if(elem->v6){
				if(elem->addrIPv6.IsEqualWith(ipIn)){
					recIn->LoadFromPointer(elem);
					found = true;
				}
			}
		}
	}

	return found;
}

//---------------------------------------------------------------------------

bool MArpCacheList::GetIPv4ByMac(MAddressMAC* macIn, DWORD* ia4In)
{
	MArpCacheRec *elem;
	bool found;

	if(macIn==NULL) return false;
	if(ia4In==NULL) return false;

	found = false;
	for(itor=theVector.begin(); itor!=theVector.end() && !found; itor++){
		elem = *itor;
		if(elem!=NULL){
			if(!elem->v6){
				if(elem->addrMAC.Compare(macIn)==0){
					found = true;
					*ia4In = elem->addrIP.GetD();
				}
			}
		}
	}

	return found;
}

bool MArpCacheList::GetIPv6ByMac(MAddressMAC* macIn, in_addr6* ia6In)
{
	MArpCacheRec *elem;
	bool found;

	if(macIn==NULL) return false;
	if(ia6In==NULL) return false;

	found = false;
	for(itor=theVector.begin(); itor!=theVector.end() && !found; itor++){
		elem = *itor;
		if(elem!=NULL){
			if(elem->v6){
				if(elem->addrMAC.Compare(macIn)==0){
					found = true;
					elem->addrIPv6.Get(ia6In);
				}
			}
		}
	}

	return found;
}

//---------------------------------------------------------------------------
